package com.menu.Service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.menu.Configuration.AlipayConfig;
import com.menu.Mapper.AddressMapper;
import com.menu.Mapper.GoodsMapper;
import com.menu.Mapper.OrderMapper;
import com.menu.Pojo.*;
import com.menu.Service.OrderService;
import com.menu.Utils.CommonUtil;
import com.menu.Utils.RedisKeyUtils;
import com.menu.Utils.RedisUtil;
import com.menu.Utils.ResponseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;


@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private GoodsMapper goodsMappper;
    @Resource
    private OrderMapper orderMapper;
    @Autowired
    private AlipayClient alipayClient;
    @Autowired
    private AlipayTradePagePayRequest pagePayRequest;
    @Autowired
    private AlipayConfig alipayConfig;
    @Resource
    private AddressMapper addressMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult generateOrder(Integer goodsId, Integer goodsNumber, Integer userId, Integer addressId) {
        Goods goods = goodsMappper.selectById(goodsId);
        if (goods == null) {
            return ResponseResult.error("商品不存在！");
        }
        Integer hasPurchase = orderMapper.countGoodsPurchase(goodsId, userId);
        if (hasPurchase == null) {
            hasPurchase = 0;
        }
        if (hasPurchase + goodsNumber > goods.getGoodsLimit()) {
            return ResponseResult.error("您已超出本次购买限制！");
        }
        if (goodsNumber > goods.getGoodsStore()) {
            return ResponseResult.error("购买大于库存！");
        }
        if (goods.getState() == 1){
            return ResponseResult.error("商品已下架！");
        }
        Order order = new Order();
        StringBuilder orderId = new StringBuilder();
        orderId.append(System.currentTimeMillis());
        orderId.append(userId);
        order.setGoodsId(goodsId);
        order.setGoodsNumber(goodsNumber);
        order.setUserId(userId);
        order.setOrderId(Long.parseLong(orderId.toString()));
        Date date=new Date();
        SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1=simpleDateFormat.format(date);
        order.setOrderTime(date1);
        Integer integer = goods.getGoodsPriceInt() * goodsNumber;
        Integer decmal = goods.getGoodsPriceDec() * goodsNumber;
        StringBuffer stringBuffer = new StringBuffer();
        if (decmal >= 100){
            integer += decmal / 100;
            decmal = decmal % 100;
        }
        stringBuffer.append(integer);
        stringBuffer.append(".");
        stringBuffer.append(decmal);
        if (decmal < 10){
            stringBuffer.append(0);
        }
        order.setOrderPrice(stringBuffer.toString());
        order.setGoodsName(goods.getGoodsName());
        AddressVO addressBO = addressMapper.select(addressId);
        if (addressBO == null || !addressBO.getUserId().equals(userId)){
            return ResponseResult.error("地址填写有误！");
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(addressBO.getMobile());
        stringBuilder.append(":");
        stringBuilder.append(addressBO.getReceiver());
        stringBuilder.append(":");
        stringBuilder.append(addressBO.getProvince());
        stringBuilder.append(addressBO.getCity());
        stringBuilder.append(addressBO.getDistrict());
        stringBuilder.append(addressBO.getDetail());
        order.setAddressMessage(stringBuilder.toString());
        order.setAddressId(addressId);
        if (redisUtil.set("OrderNo" + orderId.toString(), order, 60 * 60 * 24)
                && goodsMappper.decGoodsStore(goodsId, goodsNumber) == 1
                && orderMapper.generateOrder(order) == 1) {
            return ResponseResult.success("订单生成成功！",order.getOrderId());
        }
        return ResponseResult.error("订单生成失败！");
    }

    @Override
    public ResponseResult payForOrder(Long orderId, Integer userId) {
        Object object = redisUtil.get("OrderNo" + orderId.toString());
        Order order = null;
        if (object != null) {
            order = (Order) object;
        } else {
            order = orderMapper.selectByOrderId(orderId);
        }
        if (order == null) {
            return ResponseResult.error("订单已过期，请重新下单！");
        }
        if (!order.getUserId().equals(userId)) {
            return ResponseResult.error("非本人订单，请重新下单");
        }
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", order.getOrderId());
        bizContent.put("total_amount", order.getOrderPrice());
        bizContent.put("subject", order.getGoodsName());
        bizContent.put("product_code", "FAST_INSTANT_TRADE_PAY");
        bizContent.put("qr_pay_mode", "2");
        AlipayTradePagePayResponse alipayTradePagePayResponse = null;
        pagePayRequest.setBizContent(bizContent.toString());
        try {
            alipayTradePagePayResponse = alipayClient.pageExecute(pagePayRequest, "get");
        } catch (AlipayApiException e) {
            e.printStackTrace();
            log.info(e.getMessage());
            return ResponseResult.error(e.getMessage());
        }
        if (alipayTradePagePayResponse.isSuccess()) {
            return ResponseResult.success(alipayTradePagePayResponse.getBody());
        }
        return ResponseResult.error("服务器繁忙，请稍后重试！");
    }

    @Override
    public ResponseResult aliCallback(Map<String, String> params) {
        String out_trade_no = params.get("out_trade_no");
        if (out_trade_no == null || out_trade_no.equals(" ")) {
            return ResponseResult.error("参数有误！");
        }
        String sellerId = params.get("seller_id");
        if (!alipayConfig.getSellerId().equals(sellerId)) {
            log.info("seller_id有误！");
            return ResponseResult.error("参数有误！");
        }
        String appId = params.get("app_id");
        if (!alipayConfig.getAppid().equals(appId)) {
            log.info("appaId有误！");
            return ResponseResult.error("参数有误！");
        }
        Long orderId = null;
        try {
            orderId = Long.parseLong(out_trade_no);
        } catch (Exception e) {
            log.info("out_trade_no有误！");
        }
        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            log.info("订单不存在！");
            return ResponseResult.error("参数有误！");
        }
        String total_amount = params.get("total_amount");
        if (total_amount == null) {
            log.info("金额有误！");
            return ResponseResult.error("参数有误！");
        }
        Integer integer = order.getGoodsPriceInt() * order.getGoodsNumber();
        Integer decmal = order.getGoodsPriceDec() * order.getGoodsNumber();
        StringBuffer stringBuffer = new StringBuffer();
        if (decmal >= 100){
            integer += decmal / 100;
            decmal = decmal % 100;
        }
        stringBuffer.append(integer);
        stringBuffer.append(".");
        stringBuffer.append(decmal);
        if (decmal < 10){
            stringBuffer.append(0);
        }
        order.setOrderPrice(stringBuffer.toString());
        log.info("{}:价格",order.getOrderPrice());
        log.info("{}:支付宝返回",total_amount);
        if (!order.getOrderPrice().equals(total_amount)) {
            log.info("金额有误！");
            return ResponseResult.error("参数有误！");
        }
        String trade_status = params.get("trade_status");
        if (trade_status.equals("TRADE_SUCCESS")) {
            log.info("验证成功！");
            redisUtil.del("OrderNo" + orderId.toString());
            redisUtil.incr(RedisKeyUtils.DAY_OF_SALES,order.getGoodsNumber());
            if (orderMapper.setOrderState(orderId, 3) == 1) {
                goodsMappper.updateGoodsSales(order.getGoodsId(),order.getGoodsNumber());
                return ResponseResult.success("验证成功！");
            } else {
                log.info("{}该订单支付成功，数据库出错！", orderId);
                return ResponseResult.error("请联系客服！");
            }
        }
        return ResponseResult.error("支付出错，或失败！");
    }

    @Override
    public ResponseResult applyForRefund(Integer userId, Long orderId) {
        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null) {
            return ResponseResult.error("订单不存在！");
        }
        if (!userId.equals(order.getUserId())) {
            return ResponseResult.error("这不是您的订单！");
        }
        if (order.getState() == 4) {
            return ResponseResult.error("该商品已经申请退款，请等待商家处理！");
        }
        if (orderMapper.setOrderState(orderId, 4) == 1) {
            return ResponseResult.success("订单状态修改成功！");
        } else {
            return ResponseResult.error("订单状态修改失败，请稍后再试！");
        }
    }

    @Override
    public ResponseResult resolveRefound(Long orderId) {
        Order order = orderMapper.selectByOrderId(orderId);
        if (order.getState() != 4) {
            return ResponseResult.error("订单状态有误！");
        }
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", order.getOrderId());
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent(bizContent.toJSONString());
        AlipayTradeQueryResponse response = null;
        try {
            response =  alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return ResponseResult.error(e.getMessage());
        }
        boolean trade_success = response.getTradeStatus().equals("TRADE_SUCCESS");
        if (!trade_success) {
            return ResponseResult.error("交易关闭，或已经全额退款");
        }
        AlipayTradeRefundRequest refountRequest = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOutTradeNo(order.getOrderId().toString());
        Integer integer = order.getGoodsPriceInt() * order.getGoodsNumber();
        Integer decmal = order.getGoodsPriceDec() * order.getGoodsNumber();
        StringBuffer stringBuffer = new StringBuffer();
        if (decmal >= 100){
            integer += decmal / 100;
            decmal = decmal % 100;
        }
        stringBuffer.append(integer);
        stringBuffer.append(".");
        stringBuffer.append(decmal);
        if (decmal < 10){
            stringBuffer.append(0);
        }
        model.setRefundAmount(stringBuffer.toString());
        refountRequest.setBizModel(model);
        AlipayTradeRefundResponse refundResponse = null;
        try {
            refundResponse = alipayClient.execute(refountRequest);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return ResponseResult.error(e.getMessage());
        }
        if (refundResponse != null && refundResponse.isSuccess()) {
            orderMapper.setOrderState(order.getOrderId(),6);
            log.info("申请退款：{}成功！",orderId);
            return ResponseResult.success("退款成功！");
        }
        return ResponseResult.error("退款失败，请稍后再试！");
    }

    @Override
    public ResponseResult realData() {
        Object object = redisUtil.get(RedisKeyUtils.REAL_DATE);
        if (object != null){
            RealTimeData realTimeData = (RealTimeData) object;
            return ResponseResult.success(realTimeData);
        }
        RealTimeData realTimeData = new RealTimeData();
        realTimeData.setTotalSales(totalSales());
        realTimeData.setAveTotalSales(aveSales());
        realTimeData.setTotalclicks(totalClick());
        realTimeData.setAveTotalclicks(aveTotalClick());
        realTimeData.setTotalNumber(totalPurchase());
        realTimeData.setAveTotalNumber(aveTotalPurchase());
        Integer integer = goodsMappper.countLeave();
        if (integer == null){
            integer = 0;
        }
        realTimeData.setResidualInventory(integer);
        redisUtil.set(RedisKeyUtils.REAL_DATE,realTimeData);
        return ResponseResult.success(realTimeData);
    }

    @Override
    public ResponseResult queryByOrder(Long orderId,Integer userId) {
        OrderVo order = orderMapper.OrderVoById(orderId,userId);
        if (order == null){
            return ResponseResult.error("订单不存在！");
        }
        Integer integer = order.getGoodsPriceInt() * order.getGoodsNumber();
        Integer decmal = order.getGoodsPriceDec() * order.getGoodsNumber();
        StringBuffer stringBuffer = new StringBuffer();
        if (decmal >= 100){
            integer += decmal / 100;
            decmal = decmal % 100;
        }
        stringBuffer.append(integer);
        stringBuffer.append(".");
        stringBuffer.append(decmal);
        if (decmal < 10){
            stringBuffer.append(0);
        }
        order.setOrderPrice(stringBuffer.toString());
        return ResponseResult.success(order);
    }

    @Override
    public ResponseResult queryOrderByPage(Integer pageStart, Integer pageSize,Integer userId,Integer state) {
        PageHelper.startPage(pageStart,pageSize);
        List<OrderVo> list = orderMapper.queryOrderByPage(userId,state);
        for (OrderVo order:
             list) {
            Integer integer = order.getGoodsPriceInt() * order.getGoodsNumber();
            Integer decmal = order.getGoodsPriceDec() * order.getGoodsNumber();
            StringBuffer stringBuffer = new StringBuffer();
            if (decmal >= 100){
                integer += decmal / 100;
                decmal = decmal % 100;
            }
            stringBuffer.append(integer);
            stringBuffer.append(".");
            stringBuffer.append(decmal);
            if (decmal < 10){
                stringBuffer.append(0);
            }
            order.setOrderPrice(stringBuffer.toString());
        }
        PageInfo<OrderVo> pageInfo = new PageInfo<>(list);
        return ResponseResult.success(pageInfo);
    }

    @Override
    public ResponseResult commodityList() {
        Object object = redisUtil.get(RedisKeyUtils.GOODS_SALES_RATE);
        if (object != null){
            List<GoodsVo> list = (List<GoodsVo>) object;
            return ResponseResult.success(list);
        }else{
            List<GoodsVo> list = orderMapper.goodsSaleRate();
            redisUtil.set(RedisKeyUtils.GOODS_SALES_RATE,list);
            return  ResponseResult.success(list);
        }
    }

    @Override
    public ResponseResult getSalesNumber() {
        Object object = redisUtil.get(RedisKeyUtils.GOODS_SALES);
        if (object != null){
            List<Integer> list = (List<Integer>) object;
            return ResponseResult.success(list);
        }
        List<Integer> list = new ArrayList<>();
        for (int i = 10; i <= 100; i += 10) {
            Integer temp = goodsMappper.countVisit(1,i);
            if (temp == null ){
                list.add(0);
            }else {
                list.add(temp);
            }
        }
        redisUtil.set(RedisKeyUtils.GOODS_SALES,list,60 * 60 * 2);
        return ResponseResult.success(list);
    }

    @Override
    public ResponseResult deliverySituation() {
        Object object = redisUtil.get(RedisKeyUtils.GOODS_DELIVER);
        if (object != null){
            Map<String, Integer> map =  (Map<String, Integer>) object;
            return ResponseResult.success(map);
        }
        Map<String, Integer> map = new HashMap<>();
        Integer delivered = orderMapper.countByState(5);
        map.put("delivered",delivered);
        Integer refunded = orderMapper.countByState(6);
        map.put("refunded",refunded);
        Integer unshipped = orderMapper.countByState(3);
        map.put("unshipped",unshipped);
        redisUtil.set(RedisKeyUtils.GOODS_DELIVER,map,60*5);
        return ResponseResult.success(map);
    }

    @Override
    public ResponseResult regionalPurchase() {
        Object object = redisUtil.get(RedisKeyUtils.PROVINCE_PURCHASE);
        if (object != null){
            List<Map<String, Integer>> map =  (List<Map<String, Integer>>) object;
            return ResponseResult.success(map);
        }
        List<Map<String, Integer>> maps = orderMapper.regionalPurchase();
        redisUtil.set(RedisKeyUtils.PROVINCE_PURCHASE,maps,60 * 3);
        return ResponseResult.success(maps);
    }

    @Override
    public ResponseResult getFinish() {
        Object object = redisUtil.get(RedisKeyUtils.ORDER_FINISH);
        if (object != null){
            Integer total = (Integer) object;
            return ResponseResult.success(total);
        }else{
            Integer total = orderMapper.countByState(1);
            redisUtil.set(RedisKeyUtils.ORDER_FINISH,total,60*2);
            return ResponseResult.success(total);
        }
    }

    @Override
    public ResponseResult updateOrder(Integer state,Long orderId) {
        Integer integer = orderMapper.updateOrder(state, orderId,null);
        if (integer == 1){
            return ResponseResult.success("修改成功！");
        }
        return ResponseResult.error("修改失败！");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public ResponseResult deliverGoods(Long orderId, Long waybill, String logisticsCompany) {
        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null){
            return ResponseResult.error("订单信息不存在！");
        }
        Integer state = order.getState();
        if (state != 3){
            return ResponseResult.error("订单信息有误！");
        }
        if (orderMapper.deliverGoods(orderId,waybill,logisticsCompany) == 1){
            return ResponseResult.success("订单信息修改成功！");
        }
        return ResponseResult.error("订单信息修改失败！");
    }

    @Override
    public ResponseResult choicenessList() {
        Object object = redisUtil.get(RedisKeyUtils.GOODS_CHOICE_NESS);
        if (object != null){
            List<GoodsVo> list = (List<GoodsVo>) object;
            return ResponseResult.success(list);
        }else{
            List<GoodsVo> list = orderMapper.choicenessList();
            if (list == null){
                list = goodsMappper.choicenessList();
            }
            for (GoodsVo goodsVo:
                    list) {
                Integer integer = goodsVo.getGoodsPriceInt();
                Integer decmal = goodsVo.getGoodsPriceDec();
                StringBuffer stringBuffer = new StringBuffer();
                if (decmal >= 100){
                    integer += decmal / 100;
                    decmal = decmal % 100;
                }
                stringBuffer.append(integer);
                stringBuffer.append(".");
                stringBuffer.append(decmal);
                if (decmal < 10){
                    stringBuffer.append(0);
                }
                goodsVo.setGoodsPrice(stringBuffer.toString());
            }
            redisUtil.set(RedisKeyUtils.GOODS_CHOICE_NESS,list,24 * 60 * 60);
            return  ResponseResult.success(list);
        }
    }

    @Override
    public ResponseResult finishOrder(Long orderId, Integer userId) {
        Order order = orderMapper.selectByOrderId(orderId);
        if (order == null || order.getState() != 5){
            return ResponseResult.error("订单信息有误！");
        }
        if (orderMapper.updateOrder(1,orderId,userId) == 1){
            return ResponseResult.success("订单信息修改成功！");
        }
        return ResponseResult.error("系统繁忙！");
    }

    private String totalSales(){
        Map<String, Object> map = orderMapper.totalSales();
        if(map==null){
            return "0";
        }
        Object tempInt = map.get("totalPriceInt");
        Object tempDec = map.get("totalPriceDec");
        Integer Int = null;
        if (tempInt == null){
            Int = 0;
        }else{
            Int = Integer.parseInt(tempInt.toString()) ;
        }
        Integer Dec = null;
        if (tempDec == null){
            Dec = 0;
        }else{
            Dec = Integer.parseInt(tempDec.toString());
        }
        StringBuffer stringBuffer = new StringBuffer();
        if (Dec >= 100){
            Int += Dec / 100;
            Dec = Dec % 100;
        }
        stringBuffer.append(Int);
        stringBuffer.append(".");
        stringBuffer.append(Dec);
        return stringBuffer.toString();
    }

    private String aveSales(){
        Map<String, Object> map = orderMapper.AveSales();
        Object tempInt = 0;
        Object tempDec = 0;
        if (map != null){
            tempInt = map.get("totalPriceInt");
            tempDec = map.get("totalPriceDec");
        }
        int day = CommonUtil.getDay();
        Integer Int = null;
        if (tempInt == null){
            Int = 0;
        }else{
            Int = Integer.parseInt(tempInt.toString()) ;
        }
        Integer Dec = null;
        if (tempDec == null){
            Dec = 0;
        }else{
            Dec = Integer.parseInt(tempDec.toString());
        }
        StringBuffer stringBuffer = new StringBuffer();
        if (Dec >= 100){
            Int += Dec / 100;
            Dec = Dec % 100;
        }
        Int = Int / day;
        Dec = Dec / day;
        stringBuffer.append(Int);
        stringBuffer.append(".");
        stringBuffer.append(Dec);
        return stringBuffer.toString();
    }

    private Integer totalClick(){
        Integer total = goodsMappper.countVisitTotal(0);
        if (total == null){
            total = 0;
        }
        return total;
    }

    private Integer aveTotalClick(){
        int day = CommonUtil.getDay();
        Integer total = goodsMappper.countVisit(0,day);
        if (total == null){
            total = 0;
        }
        total /= day;
        return total;
    }

    private Integer totalPurchase(){
        Integer total = goodsMappper.countVisitTotal(1);
        if (total == null){
            total = 0;
        }
        return total;
    }

    private Integer aveTotalPurchase(){
        int day = CommonUtil.getDay();
        Integer total = goodsMappper.countVisitTotal(1);
        if (total == null){
            total = 0;
        }
        total /= day;
        return total;
    }


}
